package com.openlogic.j.client;

import static com.openlogic.j.enums.LogLevel.DEBUG;

import java.time.Duration;
import java.util.HashMap;
import java.util.Map;

import com.openlogic.j.SyncOrAsyncOrStreaming;
import com.openlogic.j.completion.CompletionHeader;
import com.openlogic.j.completion.CompletionRequest;
import com.openlogic.j.completion.CompletionResponse;
import com.openlogic.j.enums.LogLevel;
import com.openlogic.j.spi.OpenDecisionClientBuilderFactory;
import com.openlogic.j.spi.ServiceHelper;

/**
 * @ClassName: OpenDecisionClient
 * @Description: 客户端开放能力客户端
 * @author weiyongpeng
 * @date 2025年2月21日 上午9:42:42
 */
public abstract class OpenDecisionClient {
	
	// 定义抽象接口
	
	/**
	* 描述：决策流
	* @Title: decisionFlow
	* @param request
	* @return
	* @author weiyongpeng
	* @date  2025年2月24日 上午9:12:14
	 */
	public SyncOrAsyncOrStreaming<CompletionResponse> decisionFlow(CompletionRequest request) {
        return decisionFlow(new OpenDecisionClientContext(), request);
    }

    public SyncOrAsyncOrStreaming<CompletionResponse> decisionFlow(
    		OpenDecisionClientContext clientContext, CompletionRequest request) {
        throw new UnsupportedOperationException();
    }
    
    /**
    * 描述：决策树
    * @Title: decisionTree
    * @param request
    * @return
    * @author weiyongpeng
    * @date  2025年2月24日 上午9:12:02
     */
    public SyncOrAsyncOrStreaming<CompletionResponse> decisionTree(CompletionRequest request) {
        return decisionTree(new OpenDecisionClientContext(), request);
    }

    public SyncOrAsyncOrStreaming<CompletionResponse> decisionTree(
    		OpenDecisionClientContext clientContext, CompletionRequest request) {
        throw new UnsupportedOperationException();
    }
    
    /**
    * 描述：决策表
    * @Title: decisionTable
    * @param request
    * @return
    * @author weiyongpeng
    * @date  2025年2月24日 上午9:11:51
     */
    public SyncOrAsyncOrStreaming<CompletionResponse> decisionTable(CompletionRequest request) {
        return decisionTable(new OpenDecisionClientContext(), request);
    }

    public SyncOrAsyncOrStreaming<CompletionResponse> decisionTable(
    		OpenDecisionClientContext clientContext, CompletionRequest request) {
        throw new UnsupportedOperationException();
    }
    
    /**
     * 描述：交叉决策表
     * @Title: decisionCrossTable
     * @param request
     * @return
     * @author weiyongpeng
     * @date  2025年2月24日 上午9:11:51
      */
     public SyncOrAsyncOrStreaming<CompletionResponse> decisionCrossTable(CompletionRequest request) {
         return decisionCrossTable(new OpenDecisionClientContext(), request);
     }

     public SyncOrAsyncOrStreaming<CompletionResponse> decisionCrossTable(
     		OpenDecisionClientContext clientContext, CompletionRequest request) {
         throw new UnsupportedOperationException();
     }
     
     /**
      * 描述：评分卡
      * @Title: decisionScoreCard
      * @param request
      * @return
      * @author weiyongpeng
      * @date  2025年2月24日 上午9:11:51
       */
      public SyncOrAsyncOrStreaming<CompletionResponse> decisionScoreCard(CompletionRequest request) {
          return decisionScoreCard(new OpenDecisionClientContext(), request);
      }

      public SyncOrAsyncOrStreaming<CompletionResponse> decisionScoreCard(
      		OpenDecisionClientContext clientContext, CompletionRequest request) {
          throw new UnsupportedOperationException();
      }

//    public SyncOrAsyncOrStreaming<String> completion(String prompt) {
//        return completion(new OpenDecisionClientContext(), prompt);
//    }
//
//    public SyncOrAsyncOrStreaming<String> completion(OpenDecisionClientContext clientContext,
//        String prompt) {
//        throw new UnsupportedOperationException();
//    }
	
	@SuppressWarnings("rawtypes")
    public static OpenDecisionClient.Builder builder() {
        for (OpenDecisionClientBuilderFactory factory : ServiceHelper.loadFactories(OpenDecisionClientBuilderFactory.class)) {
            return factory.get();
        }
        // fallback to the default
        return DefaultOpenDecisionClient.builder();
    }

    public static class OpenDecisionClientContext {
        private final Map<String, String> headers = new HashMap<>();

        public OpenDecisionClientContext addHeaders(Map<String, String> headers) {
            this.headers.putAll(headers);
            return this;
        }

        public OpenDecisionClientContext addHeader(String key, String value) {
            headers.put(key, value);
            return this;
        }

        public Map<String, String> headers() {
            return headers;
        }

        public static OpenDecisionClientContext create() {
            return new OpenDecisionClientContext();
        }
    }

	@SuppressWarnings("unchecked")
	public abstract static class Builder<T extends OpenDecisionClient, B extends Builder<T, B>> {

		public String baseUrl="http://localhost:8080/decision/v1/"; // 默认给一个地址，可以使用域名
		public String urlParam; // url参数
		public CompletionHeader completionHeader;
		public String apiVersion;
		public String apiKey;
		public boolean isAnonymous = Boolean.FALSE;
		public Map<String, String> customHeaders;
		public boolean logRequests;
		public boolean logResponses;
		public LogLevel logLevel = DEBUG;
		public Duration callTimeout = Duration.ofSeconds(60);
		public Duration connectTimeout = Duration.ofSeconds(60);
		public Duration readTimeout = Duration.ofSeconds(60);
		public Duration writeTimeout = Duration.ofSeconds(60);

		public abstract T build();

		public Builder() {
		}

		public B baseUrl(String baseUrl) {
            if (baseUrl == null || baseUrl.trim().isEmpty()) {
                throw new IllegalArgumentException("baseUrl cannot be null or empty");
            }
            this.baseUrl = baseUrl.endsWith("/") ? baseUrl : baseUrl + "/";
            return (B) this;
        }
		
		public B urlParam(String urlParam) {
			this.urlParam = urlParam;
			return (B) this;
		}

		public B apiKey(String apiKey) {
			this.apiKey = apiKey;
			return (B) this;
		}
		
		public B apiVersion(String apiVersion) {
			this.apiVersion = apiVersion;
			return (B) this;
		}

		public B isAnonymous(Boolean isAnonymous) {
			if (!isAnonymous && (apiKey == null || apiKey.trim().isEmpty())) {
				throw new IllegalArgumentException(
						"openAiApiKey cannot be null or empty. API keys can be generated here: https://platform.openai.com/account/api-keys");
			}
			this.isAnonymous = isAnonymous;
			return (B) this;
		}

		public B completionHeader(CompletionHeader completionHeader) {
			this.completionHeader = completionHeader;
			return (B) this;
		}

		public B callTimeout(Duration callTimeout) {
			if (callTimeout == null) {
				throw new IllegalArgumentException("callTimeout cannot be null");
			}
			this.callTimeout = callTimeout;
			return (B) this;
		}

		public B connectTimeout(Duration connectTimeout) {
			if (connectTimeout == null) {
				throw new IllegalArgumentException("connectTimeout cannot be null");
			}
			this.connectTimeout = connectTimeout;
			return (B) this;
		}

		public B readTimeout(Duration readTimeout) {
			if (readTimeout == null) {
				throw new IllegalArgumentException("readTimeout cannot be null");
			}
			this.readTimeout = readTimeout;
			return (B) this;
		}

		public B writeTimeout(Duration writeTimeout) {
			if (writeTimeout == null) {
				throw new IllegalArgumentException("writeTimeout cannot be null");
			}
			this.writeTimeout = writeTimeout;
			return (B) this;
		}

		public B logRequests() {
			return logRequests(true);
		}

		public B logRequests(Boolean logRequests) {
			if (logRequests == null) {
				logRequests = false;
			}
			this.logRequests = logRequests;
			return (B) this;
		}

		public B logLevel(LogLevel logLevel) {
			if (logLevel == null) {
				logLevel = DEBUG;
			}
			this.logLevel = logLevel;
			return (B) this;
		}

		public B logResponses() {
			return logResponses(true);
		}

		public B logResponses(Boolean logResponses) {
			if (logResponses == null) {
				logResponses = false;
			}
			this.logResponses = logResponses;
			return (B) this;
		}

	}

}
